#include <iostream>
#include <cstdio>
#include <ctime>
#include <cstdarg>
#include <sys/types.h>
#include <unistd.h>

using namespace std;

// 1.日志等级
enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};

string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG:
        return "Debug";
    case INFO:
        return "Info";
    case WARNING:
        return "Warning";
    case ERROR:
        return "Error";
    case FATAL:
        return "Fatal";
    default:
        return "Unknow";
    }
}
// 2.日志打印时间
string GetTimeString()
{
    time_t curtime = time(nullptr);
    struct tm *formtime = localtime(&curtime);
    if (formtime == nullptr)
    {
        return "none time";
    }
    char buffer[1024];
    snprintf(buffer, sizeof(buffer), "%d-%d-%d %d:%d:%d",
             formtime->tm_year + 1900, formtime->tm_mon + 1, formtime->tm_mday,
             formtime->tm_hour, formtime->tm_min, formtime->tm_sec);
    return buffer;
}

/*
void LogMessage(int level, const char *format, ...)
{
    string levstr = LevelToString(level);//1.日志等级
    string timestr=GetTimeString();//获取时间字符串
    pid_t selfpid=getpid();
    cout<<"levstr: "<<levstr<<"timestr:"<<timestr<<endl;
}
*/

// 3. 代码所处的文件名/行数(__FILE__/__LINE__)

/*
void LogMessage(string filename,int line,int level, const char *format, ...)
{
    string levstr = LevelToString(level);//1.日志等级
    string timestr=GetTimeString();//获取时间字符串
    pid_t selfpid=getpid();
    cout<<"levstr: "<<levstr<<" timestr: "<<timestr<<" pid: "<<selfpid<<" filename: "<<filename<<" line: "<<line<<endl;
}
*/

// 4. 日志内容
// 4.1 获取可变参数列表的内容
// demo代码
/*
void Test(int num,...)
{
    va_list arg;
    va_start(arg,num);
    while(num)
    {
        int data=va_arg(arg,int);
        cout<<"data: "<<data<<endl;
        num--;
    }
    va_end(arg);
}
*/

void LogMessage(string filename, int line, int level, const char *format, ...)
{
    string levelstr = LevelToString(level); // 1.日志等级
    string timestr = GetTimeString();       // 获取时间字符串
    pid_t selfpid = getpid();

    char buffer[4096];
    va_list arg;
    va_start(arg, format);
    int n = vsnprintf(buffer, sizeof(buffer), format, arg);
    va_end(arg);
    cout << "[" << timestr << "]"
         << " [" << levelstr << "]"
         << " [pid:" << selfpid << "]"
         << " [" << filename << "]"
         << " [" << line << "]"
         << " [message:" << buffer << "]" << endl;
    // cout<<"levstr: "<<levstr<<" timestr: "<<timestr<<" pid: "<<selfpid<<" filename: "<<filename<<" line: "<<line<<" Log Message: "<<buffer<<endl;
}

// #define LOG(level, format, ...) LogMessage(__FILE__, __LINE__, level, format, __VA_ARGS__)
//c99/c++支持宏的可变参数列表
#define LOG(level, format, ...)                                     \
    do                                                              \
    {                                                               \
        LogMessage(__FILE__, __LINE__, level, format, ##__VA_ARGS__); \
    } while (0)
